package main

import (
	"context"
	"demo1/proto"
	"errors"
	"flag"
	"github.com/juju/ratelimit"
	"github.com/micro/go-micro/v2"
	"github.com/micro/go-micro/v2/config"
	"github.com/micro/go-micro/v2/registry"
	"github.com/micro/go-plugins/registry/etcdv3/v2"
	rl "github.com/micro/go-plugins/wrapper/ratelimiter/ratelimit/v2"
	"math/rand"
	"strconv"
	"time"
)

/**
1.go-micro v2
go get github.com/micro/go-micro/v2
2.go-plugins
go get github.com/micro/go-plugins/registry/etcdv3/v2   etcd的v3版本
go get github.com/micro/go-plugins/wrapper/ratelimiter/ratelimit/v2  go-plugin库对github.com/juju/ratelimit限流库的二次封装
go get github.com/micro/go-plugins/wrapper/breaker/hystrix/v2  go-plugin库对github.com/afex/hystrix-go熔断库的二次封装,client.go端使用
 */

type StudentOp struct{
	address string
}
var students = map[string]proto.Student{
	"ztind":proto.Student{Id:1,Name:"ztind",Age:18},
	"jimmy":proto.Student{Id:2,Name:"jimmy",Age:19},
	"tom":proto.Student{Id:3,Name:"tom",Age:20},
}
func (s *StudentOp)	GetStudent(_ context.Context, in *proto.ReqStudent, out *proto.Student) error{
	student := students[in.Name]
	if student.Id == 0{
		return errors.New("not have this student")
	}
	student.Name = s.address+ " "+student.Name
	*out = student
	return nil
}
type ConfigModel struct {
	Version string
	StudentServer struct{
		Name string
	}
	Etcd struct {
		Addrs []string
		Username string
		Password string
	}
}
func main(){
	//从命令行读取-f指令的配置文件路径
	confPath := flag.String("f","../config/config.json","the path of config")
	flag.Parse()//解析
	//config加载配置文件
	err := config.LoadFile(*confPath)
	if err!=nil{
		panic(err)
	}
	//将文件写入结构体对象
	conf := new(ConfigModel)
	config.Scan(conf)

	etcdv3Reg := etcdv3.NewRegistry(
		etcdv3.Auth(conf.Etcd.Username,conf.Etcd.Password),//设置etcd用户名密码
		func(op *registry.Options){
			op.Addrs = conf.Etcd.Addrs //etcd集群
		},
	)

	br := ratelimit.NewBucketWithRate(float64(2), int64(2))//参一：速率,每秒存放(生成)2个token，参二：容量,token存储容量 https://www.cnblogs.com/cjsblog/p/9379516.html
	service := micro.NewService(
		micro.Name(conf.StudentServer.Name),
		micro.Version(conf.Version),
		micro.Registry(etcdv3Reg),//将服务注册到tecd注册中心,内部使用etcd v3版本客户端api实现了LB
		micro.WrapHandler(rl.NewHandlerWrapper(br,false)),//服务端限流实现
		)
	rand.Seed(time.Now().Unix())
	i := strconv.Itoa(rand.Intn(100))
	proto.RegisterStudentServerHandler(service.Server(),&StudentOp{address:i})//注册服务
	service.Init()
	//启动服务监听
	if err := service.Run();err != nil {
		panic(err)
	}
}
